package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
	"xs.jsjb/internal/app"
	"xs.jsjb/pkg/cache"
	"xs.jsjb/pkg/conf"
	"xs.jsjb/pkg/database"
	"xs.jsjb/pkg/logger"
)

func main() {
	//配置初始化
	config, err := conf.Init()
	if err != nil {
		log.Fatalf("conf.Build failed, err: %+v", err)
	}

	//初始化log
	if err = logger.Init(config); err != nil {
		log.Fatalf("log.Build failed, err: %+v", err)
	}

	//初始化database
	db, err := database.Init(config)
	if err != nil {
		zap.L().Error("database.Build failed", zap.Error(err))
		return
	}

	//初始化cache
	rbd, err := cache.Init(config)
	if err != nil {
		zap.L().Error("cache.Build failed", zap.Error(err))
		return
	}
	if config.Mode == gin.ReleaseMode {
		gin.SetMode(gin.ReleaseMode) // gin设置成发布模式
	}
	// 6. init app
	router := app.Build(db, rbd)
	gracefulShutDown(router, config.System.Port)

}

func gracefulShutDown(router *gin.Engine, port int) {

	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", port),
		Handler: router,
	}

	// 7. start http server and gracefully shutdown
	go func() {
		// service connections
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %+v\n", err)
		}
	}()

	// Wait for interrupt signal to gracefully shutdown the server with
	// a timeout of 5 seconds.
	quit := make(chan os.Signal)
	// kill (no param) default send syscanll.SIGTERM
	// kill -2 is syscall.SIGINT
	// kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Println("Shutdown Server ...")

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	// catching ctx.Done(). timeout of 5 seconds.
	select {
	case <-ctx.Done():
		log.Println("timeout of 5 seconds.")
	}
	log.Println("Server exiting")
}
